"""
模糊关键词处理和单位澄清功能模块

该模块包含处理模糊提问返回单位列表供用户澄清的相关功能
"""

import logging
from typing import Dict, Any, List, Optional, Union
from fastapi import HTTPException

# 注意：为了避免循环导入，get_user_available_units和extract_settlement_keyword函数将在需要时延迟导入

# 复制必要的工具函数到utils_2中，避免循环导入
def safe_extract_unit_name(unit: Any, default: str = "未知") -> str:
    """
    安全地从单位对象中提取单位名称
    
    Args:
        unit: 单位对象（可能是字典、None或其他类型）
        default: 默认返回值
        
    Returns:
        str: 单位名称或默认值
    """
    if not isinstance(unit, dict):
        return default
        
    unit_name = unit.get("unitFullName")
    if unit_name and isinstance(unit_name, str) and unit_name.strip():
        return unit_name.strip()
    else:
        return default

def safe_extract_unit_id(unit: Any, default: str = "未知") -> str:
    """
    安全地从单位对象中提取单位ID
    
    Args:
        unit: 单位对象（可能是字典、None或其他类型）
        default: 默认返回值
        
    Returns:
        str: 单位ID或默认值
    """
    if not isinstance(unit, dict):
        return default
        
    unit_id = unit.get("unitId")
    if unit_id and isinstance(unit_id, str) and unit_id.strip():
        return unit_id.strip()
    else:
        return default

def calculate_location_similarity(keyword: str, unit_name: str) -> float:
    """
    计算地理位置名称的相似度，简化版本不区分停车场和公司
    
    Args:
        keyword: 用户查询的关键词
        unit_name: 单位名称
        
    Returns:
        float: 相似度得分（0-1之间）
    """
    from difflib import SequenceMatcher
    
    # 计算完整名称的相似度
    full_similarity = SequenceMatcher(None, keyword.lower(), unit_name.lower()).ratio()
    
    # 处理关键词和单位名称，移除常见后缀
    processed_keyword = process_text_suffixes(keyword.lower())
    processed_unit_name = process_text_suffixes(unit_name.lower())
    
    # 计算处理后的相似度
    processed_similarity = SequenceMatcher(None, processed_keyword, processed_unit_name).ratio()
    
    # 子串匹配得分
    substring_score = 0.0
    if processed_keyword in processed_unit_name:
        substring_score = 0.7  # 降低子串匹配得分，避免"P+R"这样的通用词影响过大
    elif processed_unit_name in processed_keyword:
        substring_score = 0.6  # 降低子串匹配得分
    
    # 返回最高相似度
    return max(full_similarity, processed_similarity, substring_score)

def process_text_suffixes(text: str) -> str:
    """
    处理文本，移除常见单位后缀
    
    Args:
        text: 原始文本（可以是关键词或单位名称）
        
    Returns:
        str: 处理后的文本
    """
    suffixes = ['公司', '有限公司', '分公司', '集团', '子公司']
    processed_text = text.lower().strip()
    for suffix in suffixes:
        if processed_text.endswith(suffix):
            processed_text = processed_text[:-len(suffix)]
            break
    return processed_text


def is_ambiguous_keyword(keyword: str) -> bool:
    """
    检测关键词是否为模糊关键词
    
    Args:
        keyword: 用户查询的关键词
        
    Returns:
        bool: 是否为模糊关键词
    """
    if not keyword:
        return False
    
    keyword_lower = keyword.lower().strip()
    
    # 检查关键词是否过短（长度<=1的单个词汇通常比较模糊）
    if len(keyword_lower) <= 1:
        return True
    
    # 定义行业模糊关键词列表（只有行业类型的关键词才需要澄清）
    industry_ambiguous_keywords = [
        # 交通行业
        '出租', '租赁', '地铁', '公交', '巴士', '客运', '货运', '物流', '运输',
        '快递', '航空', '铁路', '公路', '港口', '机场', '交通', '停车场', '加油站', 'P+R',
        
        # 能源行业
        '石油', '石化', '化工', '电力', '能源', '煤炭', '矿产', '燃气',
        
        # 建筑房地产
        '建筑', '房地产', '物业', '开发', '施工', '装修',
        
        # 商业服务
        '贸易', '批发', '零售', '餐饮', '酒店', '旅游', '商场', '超市',
        
        # 公共服务
        '医疗', '医院', '教育', '学校', '银行', '金融', '保险', '证券', '投资',
        
        # 其他行业
        '制造', '加工', '科技', '信息', '软件', '网络', '通信', '电子', '机械',
        '设备', '汽车', '农业', '林业', '渔业', '水利', '环保', '市政'
    ]
    
    # 检查关键词是否为行业模糊关键词
    for ambiguous_word in industry_ambiguous_keywords:
        # 只有当关键词完全匹配行业词汇时，才认为是模糊关键词
        if keyword_lower == ambiguous_word:
            return True
    
    # 具体的地点名称（如"北京"、"北京首都国际机场"）应该是明确的，不视为模糊关键词
    return False


async def find_similar_units_by_keyword(phone_number: str, keyword: str, max_results: int = 5) -> List[Dict[str, Any]]:
    """
    根据模糊关键词查找相似的单位列表
    
    Args:
        phone_number: 用户手机号
        keyword: 模糊关键词
        max_results: 最大返回结果数量
        
    Returns:
        List[Dict]: 相似单位列表，包含单位ID、名称和相似度
        
    Raises:
        HTTPException: 如果获取单位列表失败
    """
    try:
        # 延迟导入以避免循环导入
        from utils import get_user_available_units
        
        # 获取用户可查询的单位列表
        available_units = await get_user_available_units(phone_number, return_full_info=True)
        
        if not available_units:
            return []
        
        # 计算每个单位与关键词的相似度
        similarity_scores = []
        for unit in available_units:
            if isinstance(unit, dict):
                unit_name = safe_extract_unit_name(unit)
                unit_id = safe_extract_unit_id(unit)
                
                # 使用地理位置相似度计算方法
                similarity = calculate_location_similarity(keyword.lower().strip(), unit_name.lower().strip())
                
                similarity_scores.append({
                    'unit_id': unit_id,
                    'unit_name': unit_name,
                    'similarity': similarity,
                    'unit_info': unit
                })
        
        # 按相似度降序排序
        similarity_scores.sort(key=lambda x: x['similarity'], reverse=True)
        
        # 返回前max_results个结果
        return similarity_scores[:max_results]
        
    except Exception as e:
        logging.error(f"查找相似单位失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"查找相似单位失败: {str(e)}")


async def handle_ambiguous_keyword_response(phone_number: str, keyword: str, user_query: str) -> Dict[str, Any]:
    """
    处理模糊关键词，返回相似单位列表和反问消息
    
    Args:
        phone_number: 用户手机号
        keyword: 模糊关键词
        user_query: 原始用户查询
        
    Returns:
        Dict: 包含相似单位列表和反问消息的响应
    """
    # 查找相似单位
    similar_units = await find_similar_units_by_keyword(phone_number, keyword, max_results=5)
    
    if not similar_units:
        # 如果没有找到相似单位，返回错误信息
        if keyword == "查询":
            return {
                'is_ambiguous': True,
                'similar_units': [],
                'response_message': "您的查询比较模糊，我无法找到相关的单位。请提供更具体的单位名称。"
            }
        else:
            return {
                'is_ambiguous': True,
                'similar_units': [],
                'response_message': f"您查询的关键词'{keyword}'比较模糊，我无法找到相关的单位。请提供更具体的单位名称。"
            }
    
    # 构建相似单位列表 - 优化格式便于后续匹配
    unit_list_text = []
    for i, unit in enumerate(similar_units, 1):
        # 使用更清晰的格式，便于后续正则表达式匹配
        unit_list_text.append(f"{i}. {unit['unit_name']}")
    
    units_text = "\n".join(unit_list_text)
    
    # 构建反问消息（特殊处理'查询'关键词）
    if keyword == "查询":
        response_message = f"""您的查询比较模糊，我找到了以下相似的单位：

{units_text}

请问您想查询以下哪个单位？请回复对应的数字（1-{len(similar_units)}）或直接告诉我具体的单位名称。"""
    else:
        response_message = f"""您查询的关键词'{keyword}'比较模糊，我找到了以下相似的单位：

{units_text}

请问您想查询以下哪个单位？请回复对应的数字（1-{len(similar_units)}）或直接告诉我具体的单位名称。"""
    
    return {
        'is_ambiguous': True,
        'similar_units': similar_units,
        'response_message': response_message
    }


async def extract_settlement_keyword_with_ambiguity_check(user_query: str, phone_number: str, history: Optional[List[Dict[str, Any]]] = None) -> Union[str, Dict[str, Any]]:
    """
    增强版的关键词提取函数，支持模糊关键词检测和处理
    
    Args:
        user_query: 用户查询
        phone_number: 用户手机号
        history: 对话历史
        
    Returns:
        Union[str, Dict]: 如果关键词明确则返回关键词字符串，如果模糊则返回处理响应
    """
    # 延迟导入以避免循环导入
    from utils import extract_settlement_keyword
    
    # 首先调用原有的关键词提取函数
    keyword = await extract_settlement_keyword(user_query, history, phone_number)
    
    # 检查是否为模糊关键词或无法提取到有效关键词
    if is_ambiguous_keyword(keyword) or keyword == "查询":
        logging.info(f"[模糊关键词检测] 检测到模糊关键词: {keyword}")
        
        # 处理模糊关键词
        return await handle_ambiguous_keyword_response(phone_number, keyword, user_query)
    
    # 如果关键词明确，直接返回
    return keyword